package com.yifi.service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Arrays;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import com.baidubce.BceClientConfiguration;
import com.baidubce.auth.DefaultBceCredentials;
import com.baidubce.services.tsdb.TsdbClient;
import com.baidubce.services.tsdb.model.Datapoint;
import com.baidubce.services.tsdb.model.GetRowsWithSqlResponse;
import com.baidubce.services.tsdb.model.WriteDatapointsRequest;
import com.baidubce.services.tsdb.model.WriteDatapointsResponse;
import com.jfinal.plugin.activerecord.Record;
import com.yifi.common.DBHelper;

public class TSDBService {
	public TsdbClient tsdbClient;

	public TSDBService() {
		this.tsdbClient = get_tsdb_client();
	}

	public TsdbClient get_tsdb_client() {

		// 创建配置
		// 获取AK/SK: https://cloud.baidu.com/doc/Reference/s/9jwvz2egb
		String ACCESS_KEY_ID = "19cda41db5b54598815874d28561b295"; // 用户的Access Key ID
		String SECRET_ACCESS_KEY = "cf67d5fbb89243f7bf5c527add6ccc57"; // 用户的Secret Access Key
		String ENDPOINT = "tsdb2iot.tsdb-fqqv2y35eym7.tsdb.iot.bj.baidubce.com"; // 用户的时序数据库域名，形式如databasename.tsdb.iot.gz.baidubce.com
		BceClientConfiguration config = new BceClientConfiguration()
				.withCredentials(new DefaultBceCredentials(ACCESS_KEY_ID, SECRET_ACCESS_KEY)).withEndpoint(ENDPOINT);

		// 初始化一个TsdbClient
		TsdbClient tsdbClient = new TsdbClient(config);
		return tsdbClient;
	}

	public void shutdown() {

		tsdbClient.shutdown();
	}

	public WriteDatapointsResponse addDatapoints_dcs(String metric, JSONArray jsonArray_hist) {

//		String jdata_hist =" [{\"c_id_sb\":\"01\",\"c_id_cs\":\"0102\",\"c_code_cs\":\"002\",\"c_value\":\"11\",\"c_date\":\"1637131684\"}]";
//		JSONArray jsonarr_hist = JSONArray.fromObject(jdata_hist);

		List<Datapoint> list_datapoint = new ArrayList<Datapoint>();
		for (int i = 0; i < jsonArray_hist.size(); i++) {
			JSONObject jsonJ = jsonArray_hist.getJSONObject(i);

			String c_id_sb = jsonJ.getString("c_id_sb");
			// String c_id_cs = jsonJ.getString("c_id_cs");
			String c_code_cs = jsonJ.getString("c_code_cs");
			long t_date = Long.parseLong(jsonJ.getString("c_date"));
			double d_value = Double.parseDouble(jsonJ.getString("c_value"));
			// String d_value = jsonJ.getString("c_value");

			/*
			 * Datapoint datapoint = new Datapoint() .withMetric(metric) // 设置Metric
			 * //.withField("dcs") // 设置数据点域，可选，不填使用默认域名 value,长度为1-40个字符。
			 * 只能包含大小写字母、数字、下划线，必须以字母开头 .addTag("c_id_sb",c_id_sb ) // 设置Tag
			 * .addTag("c_id_cs", c_id_cs) // 设置Tag .addTag("c_code_cs", c_code_cs) // 设置Tag
			 * .addDoubleValue(t_date, d_value); // 添加Double类型数据点
			 * list_datapoint.add(datapoint);
			 */

			Datapoint datapoint_hist = new Datapoint().withMetric("hehai") // 设置Metric
					.withField("c_cs_" + c_code_cs) // 设置数据点域，可选，不填使用默认域名 value
					.addTag("c_sb", c_id_sb) // 设置Tag
					// .addStringValue(t_date, d_value);
					.addDoubleValue(t_date, d_value); // 添加Double类型数据点
			list_datapoint.add(datapoint_hist);
		}
		return tsdbClient.writeDatapoints(list_datapoint);
	}

	public WriteDatapointsResponse addDatapoints_yf(String metric, List<Record> list_hist) {

		List<Datapoint> list_datapoint = new ArrayList<Datapoint>();
		for (Record re_hist : list_hist) {

			String c_id_sb = DBHelper.GetString(re_hist, "deviceid");
			String c_id_cs = DBHelper.GetString(re_hist, "paramid");
			long t_date = re_hist.getBigDecimal("rctime_t").longValue();
			double d_value = DBHelper.GetDouble(re_hist, "curvalue");

			Datapoint datapoint = new Datapoint().withMetric(metric) // 设置Metric
					// .withField(field) // 设置数据点域，可选，不填使用默认域名 value
					.addTag("c_id_sb", c_id_sb) // 设置Tag
					.addTag("c_id_cs", c_id_cs) // 设置Tag
					.addDoubleValue(t_date, d_value); // 添加Double类型数据点
			list_datapoint.add(datapoint);
		}
		return tsdbClient.writeDatapoints(list_datapoint);
	}

	/**
	 * 写入单域数据点 注意：当写入的metric、field、tags、timestamp都相同时，后写入的value会覆盖先写入的value。
	 */
	public WriteDatapointsResponse writeSingleFieldDatapoints() {
		/*
		 * String metric = "wind"; // metric String tagKey = "city"; // 标签名称 String
		 * tagValue = "ShangHai"; // 标签值 String field = "direction"; // 域
		 */
		String metric = "langfang"; // metric

		/*
		 * String field = "value"; // 域：应该只包含字母、数字、下划线，并以字母开头 //标签至少有一个，最多20个 String
		 * tagKey = "cs"; // 标签名称 String tagValue =
		 * "786f8203-4982-411f-9bc7-c2d31a23d671"; // 标签值
		 */

		// 创建数据点
		List<Datapoint> datapoints = Arrays.asList(new Datapoint().withMetric(metric) // 设置Metric
				// .withField(field) // 设置数据点域，可选，不填使用默认域名 value
				.addTag("c_id_sb", "08a06659-99f3-447a-a1b3-4df02d7f1360") // 设置Tag
				.addTag("c_id_cs", "6418da11-b653-4004-8731-8a881e2b53dd") // 设置Tag
				.addDoubleValue(System.currentTimeMillis() - 2000, 54.5));// 添加一个数据点
		// .addDoubleValue(System.currentTimeMillis()+2000, 223.5)); // 添加一个数据点

		return tsdbClient.writeDatapoints(datapoints);
	}

	/**
	 * 一个Datapoint对象可以同时添加多个数据点，这些数据点使用相同的metric、标签和域。
	 * 多个相同metric和标签的数据放入同一个Datapoint对象，可以减少payload。
	 *
	 * @return
	 */
	public WriteDatapointsResponse addMultipleDatapoint() {
		String metric = "wind"; // metric
		String tagKey = "city"; // 标签名称
		String tagValue = "ShangHai"; // 标签值
		String field = "direction"; // 域
		Datapoint datapoint = new Datapoint().withMetric(metric) // 设置Metric
				.withField(field) // 设置数据点域，可选，不填使用默认域名 value
				.addTag(tagKey, tagValue) // 设置Tag
				.addDoubleValue(System.currentTimeMillis(), 0.1) // 添加一个数据点
				.addDoubleValue(System.currentTimeMillis() + 1, 0.2); // 再添加一个数据点

		return tsdbClient.writeDatapoints(Arrays.asList(datapoint));
	}

	/**
	 * Datapoint对象可以添加double，long和String类型的数据点。
	 * 对于同一个field，如果写入了某个数据类型的value之后，相同的field不允许写入其他数据类型。
	 *
	 * @return
	 */
	public WriteDatapointsResponse addMultipleTypeDatapoint() {
		String tagKey = "city"; // 标签名称
		String tagValue = "ShangHai"; // 标签值
		String field = "direction"; // 域
		// 添加Double类型数据点
		Datapoint datapoint1 = new Datapoint().withMetric("wind") // 设置Metric
				.withField(field) // 设置数据点域，可选，不填使用默认域名 value
				.addTag(tagKey, tagValue) // 设置Tag
				.addDoubleValue(System.currentTimeMillis(), 0.1); // 添加Double类型数据点

		// 添加Long类型数据点
		Datapoint datapoint2 = new Datapoint().withMetric("memory_usage").addTag(tagKey, tagValue)
				.addLongValue(System.currentTimeMillis(), 10L);

		// 添加String类型数据点
		Datapoint datapoint3 = new Datapoint().withMetric("error_message").addTag(tagKey, tagValue)
				.addStringValue(System.currentTimeMillis(), "string");

		return tsdbClient.writeDatapoints(Arrays.asList(datapoint1, datapoint2, datapoint3));
	}

	/**
	 * 写入多域数据点 不同的域并不需要同时写入，可以认为不同的域都是独立的。
	 * 但如果查询时要用一条语句查出来，需要保证metric、所有的tag、时间戳都是一致的。
	 */
	public WriteDatapointsResponse writeMultipleFieldDatapoints() {
		String metric = "wind"; // metric
		String tagKey = "city"; // 标签名称
		String tagValue = "ShangHai"; // 标签值
		String field1 = "direction"; // 域1
		String field2 = "speed"; // 域2
		long TIME = System.currentTimeMillis(); // 时间

		// 添加field_1的数据点
		Datapoint datapoint1 = new Datapoint().withMetric(metric) // 设置Metric
				.withField(field1) // 设置域1
				.addTag(tagKey, tagValue) // 设置Tag
				.addDoubleValue(TIME, 0.1); // 指定时间写入Double类型数据点

		// 添加field_2的数据点
		Datapoint datapoint2 = new Datapoint().withMetric(metric) // 设置Metric,需要和field1的一样
				.withField(field2) // 设置域2
				.addTag(tagKey, tagValue) // 设置Tag，需要和field1的一样
				.addLongValue(TIME, 10L); // 指定时间添加Long类型数据点，时间需要和field_1的一样

		return tsdbClient.writeDatapoints(Arrays.asList(datapoint1, datapoint2));
	}

	/**
	 * 写入数据点的gzip压缩说明 v0.10.10版本的sdk中，写入数据点默认开启gzip压缩。 如果不需要使用gzip压缩，可参考如下代码：
	 */
	public void writeNotUseGzip() {
		String metric = "wind"; // metric
		String tagKey = "city"; // 标签名称
		String tagValue = "ShangHai"; // 标签值

		// 创建数据点
		List<Datapoint> datapoints = Arrays.asList(new Datapoint().withMetric(metric) // 设置Metric
				.addTag(tagKey, tagValue) // 设置Tag
				.addDoubleValue(System.currentTimeMillis(), 0.1)); // 添加一个数据点
		boolean useGzip = false; // 不使用gzip

		tsdbClient.writeDatapoints(new WriteDatapointsRequest().withDatapoints(datapoints), useGzip);
	}

	public void get_datapoint(String sql) {

		GetRowsWithSqlResponse rows = tsdbClient.getRowsWithSql(sql);
		List<List<Object>> list = rows.getRows();
		for (List<Object> re : list) {

			System.out.println("时间：" + stampToDate(re.get(0).toString()) + ";参数：" + re.get(1) + ";值：" + re.get(2));
		}
	}

	/*
	 * 将时间转换为时间戳
	 */
	public String dateToStamp(String s) {
		String res;
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date date = null;
		try {
			date = simpleDateFormat.parse(s);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		long ts = date.getTime();
		res = String.valueOf(ts);
		return res;
	}

	/*
	 * 将时间戳转换为时间
	 */
	public String stampToDate(String s) {
		String res;
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		long lt = new Long(s);
		Date date = new Date(lt);
		res = simpleDateFormat.format(date);
		return res;
	}

	/*
	 * 将时间戳转换为时间
	 */
	public String stampToDate(String s, String format) {
		String res;
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);// yyyy-MM-dd HH:mm:ss
		long lt = new Long(s);
		Date date = new Date(lt);
		res = simpleDateFormat.format(date);
		return res;
	}

}
